/**
 * 
 */
package jzombies;

import repast.simphony.context.Context;
import repast.simphony.context.DefaultContext;
import repast.simphony.context.space.continuous.ContinuousSpaceFactory;
import repast.simphony.context.space.continuous.ContinuousSpaceFactoryFinder;
import repast.simphony.context.space.graph.NetworkBuilder;
import repast.simphony.context.space.grid.GridFactory;
import repast.simphony.context.space.grid.GridFactoryFinder;
import repast.simphony.dataLoader.ContextBuilder;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.parameter.Parameters;
import repast.simphony.random.RandomHelper;
import repast.simphony.space.continuous.ContinuousSpace;
import repast.simphony.space.continuous.NdPoint;
import repast.simphony.space.continuous.RandomCartesianAdder;
import repast.simphony.space.grid.Grid;
import repast.simphony.space.grid.GridBuilderParameters;
import repast.simphony.space.grid.SimpleGridAdder;
import repast.simphony.space.grid.WrapAroundBorders;

/**
 * @author grace
 *
 */
// to collect data, make the builder into a context itself.
// so now it will contain agents which we can access.

//public class JZombiesBuilder implements ContextBuilder<Object> {
public class JZombiesBuilder extends DefaultContext<Object>
	implements ContextBuilder<Object> {

	@Override
	public Context build(Context<Object> context) {
		// usually set to project name and match context id in context.xml file
		context.setId("jzombies");
		
		// build infected network
		// true = want directed network with links from infecting zombie to 
		// newly created zombie
		NetworkBuilder<Object> netBuilder = new NetworkBuilder<Object>
			("infection network", context, true);
		netBuilder.buildNetwork();
		
		// create ContinuousSpace projection
		// get factory of appropriate type
		ContinuousSpaceFactory spaceFactory =
			ContinuousSpaceFactoryFinder.createContinuousSpaceFactory(null);
		// use factory to create actual ContinuousSpace
		ContinuousSpace<Object> space =
			spaceFactory.createContinuousSpace("space", // name of space
					context, // context to associate space with
					new RandomCartesianAdder<Object>(), // where objects are added initially
					new repast.simphony.space.continuous.WrapAroundBorders(), // border
					// ^ describes what happens at edge
					// WrapAroundBorders = turn space into a torus
					// StrictBorders = agents cannot cross
					50,50); // dimension of the grid
		
		// create Grid projections (similar descriptions as above)
		GridFactory gridFactory = GridFactoryFinder.createGridFactory(null);
		Grid<Object> grid = gridFactory.createGrid("grid", context,
				// slightly different from above
				new GridBuilderParameters<Object>(new WrapAroundBorders(),
						new SimpleGridAdder<Object>(),
						// true = multiple occupancy is allowed
						true, 50, 50));
		
		// create zombies and add to context
		// make zombie count into a parameters
		//int zombieCount = 5;
		Parameters params = RunEnvironment.getInstance().getParameters();
		int zombieCount = (Integer) params.getValue("zombie_count");
		for (int i=0; i<zombieCount; i++) {
			context.add(new Zombie(space, grid));
		}
		
		// create humans and add to context
		//int humanCount = 100;
		int humanCount = (Integer) params.getValue("human_count");
		for (int i=0; i<humanCount; i++) {
			int energy = RandomHelper.nextIntFromTo(4,10);
			context.add(new Human(space, grid, energy));
		}
		
		// move agents to grid that corresponds to their ContinuousSpace location
		for (Object obj : context) {
			NdPoint pt = space.getLocation(obj);
			grid.moveTo(obj, (int)pt.getX(), (int)pt.getY());
		}
		
		return context;
	}
	
	// get human count
	public int getHumanCount() {
		return getObjects(Human.class).size();
	}
	
	// get zombie count
	public int getZombieCount() {
		return getObjects(Zombie.class).size();
	}

}
